function CTextPane(Params, Effects, Begin, End) {
	var params = Params;
	var effects = Effects;
	var that = this;
	var begin = -1;
	var end = -1;
	var loaded = false;
	var loading = false;
	this.bufferable = false; // TODO change that as soon as buffer is enabled

	if (!(typeof (Begin) === 'undefined')) {
		begin = Begin;
	}
	if (!(typeof (End) === 'undefined')) {
		end = End;
	}
	if (effects != null) {
		buffereable = false;
	}

	this.draw = function(ctx, step, zoom) {
		/* only render if it is supposed to be visible */
		if ((begin < step) && (end > step || end <= -1)) {
			/* render to context */
			textpane(ctx, zoom);
		}
	};
	this.custom = function(type, ctx, zoom) {
		/* just a dummy */
	};
	this.applyEffects = function(steppercent, step) {
		if (effects == null) {
			return;
		}
		for ( var i = 0; i < effects.length; i++) {
			effects[i].apply(that, steppercent, step);
		}
	};

	/* don't draw things that are not visible to improve the performance */
	function clipping(x, y, size, scalar) {
		return true;
		if (lengthOf(dx / scalar + x, dy / scalar + y) < size
				+ (screen_radius / scalar)) {
			return true;
		}
		return false;
	}
	/* helper to calc length of a vect */
	function lengthOf(a, b) {
		return Math.sqrt((a * a) + (b * b));
	}

	function getContent(file) {
		var client = new XMLHttpRequest();
		client.open('GET', '../' + file);
		client.onreadystatechange = function() {
			var str = client.responseText;
			alert(str);
			prepare(str);
		}
		client.send();
	}

	function prepare(str) {
		// init params.longestline to 0 to make the code work
		params.longestline = 0;

		params.line = str.split("\n");

		// determine longest line
		for ( var i = 0; i < params.line.length; i++) {
			if (params.line[i].length > params.longestline) {
				params.longestline = params.line[i].length;
			}
		}

		if (params.monospaced == true) {
			// fill up lines with whitespace
			for ( var i = 0; i < params.line.length; i++) {
				while (params.line[i].length < params.longestline) {
					params.line[i] += " ";
				}
			}
		}

		// update params for displaying correctly
		params.size = params.height / params.line.length;
		if (params.width / params.longestline < params.size / 3) {
			params.size = params.width / params.longestline;
		}
		// now everything is loaded
		loaded = true;
		loading = false;
	}

	function load(file) {
		if (loading == false) {
			loading = true;
			if (params.isString == true) {
				prepare(file);
			} else {
				getContent(file);
			}
		}
	}

	function textpane(ctx, scalar) {
		if (loaded == false) {
			load(params.file);
		} else {
			// box(ctx, scalar);
			for ( var i = 0; i < params.line.length; i++) {
				var dx = -Math.sin(params.angle * Math.PI / 180.0)
						* (((i) * params.size) - params.height / 2);
				var dy = Math.cos(params.angle * Math.PI / 180.0)
						* (((i) * params.size) - params.height / 2);
				text(ctx, scalar, params.x + dx, params.y + dy, params.line[i]);
			}
		}
	}

	/* using scalar instead of zoom, because I did just copy from core 1.0 */
	function text(ctx, scalar, x, y, str) {
		/* this is not nice, but it improves performance drastically */
		if (clipping(x, y, params.size / 3 * str.length, scalar) == true
				&& (params.size * scalar) > 1 / 2) {
			ctx.translate(x * scalar, (y) * scalar);
			ctx.rotate((params.angle) * Math.PI / 180);
			ctx.translate(-x * scalar, -(y) * scalar);
			if(params.monospaced == true) {
				ctx.font = (params.size * scalar) + "px 'Courier New'";
			} else {
				ctx.font = (params.size * scalar) + "px 'Helvetica'";
			}
			ctx.textAlign = 'center';
			ctx.fillText(str, (x) * scalar, (y - params.size / 3) * scalar);
			ctx.translate(x * scalar, (y) * scalar);
			ctx.rotate((-params.angle) * Math.PI / 180);
			ctx.translate(-x * scalar, -(y) * scalar);
		}
	}
	function box(ctx, scalar) {
		if (clipping(params.x, params.y,
				lengthOf(params.width, params.height) / 2, scalar) == true) {
			var box_y = params.y - (params.height / 2);
			var box_x = params.x - (params.width / 2);
			ctx.translate((box_x + params.width / 2) * scalar,
					(params.y + params.height / 2) * scalar);
			ctx.rotate((params.angle) * Math.PI / 180);
			ctx.translate(-(box_x + params.width / 2) * scalar,
					-(box_y + params.height / 2) * scalar);
			var xpos = box_x * scalar;
			var ypos = box_y * scalar;

			ctx.strokeRect(xpos, ypos, params.width * scalar, params.height
					* scalar);
			ctx.translate((box_x + params.width / 2) * scalar,
					(box_y + params.height / 2) * scalar);
			ctx.rotate((-params.angle) * Math.PI / 180);
			ctx.translate(-(box_x + params.width / 2) * scalar,
					-(box_y + params.height / 2) * scalar);
		}
	}
}